﻿
using System;
using UnityEngine;

namespace Neuron
{
	public class CustomSkelTransformsPhysicalReference
	{
		GameObject referenceObject = null;
		Transform[] referenceTransforms = null;

		public bool Init( Transform root, string prefix, Transform[] bound_transforms )
		{
			if( root == null )
			{
				Debug.LogError(	"[CustomSkelTransformsPhysicalReference] Invalid root Transform" );
				return false;
			}

			// check if there is enough Rigidbody Component on the bones,
			// if not return false to prevent init reference_object
			if( !CheckRigidbodies( bound_transforms ) )
			{
				Debug.LogError(	string.Format(
					"[CustomSkelTransformsPhysicalReference] Trying to use physics update but no Rigidbody Component in Actor \"{0}\". Did you forget to add Rigidbody Component?",
					root.gameObject.name ), root );
				return false;
			}

			// duplicate bound object as reference object,
			// we only use this reference object's transforms to get world transforms
			referenceObject = (GameObject)GameObject.Instantiate( root.gameObject, root.position, root.rotation );
			referenceObject.name = string.Format( "{0} (neuron reference)", root.gameObject.name );
			referenceTransforms = new Transform[(int)NeuronBones.NumOfBones];
			NeuronHelper.Bind( referenceObject.transform, referenceTransforms, prefix, false );

			CustomSkelTransformsInstance referenceInstance = referenceObject.GetComponent<CustomSkelTransformsInstance>();
			if( referenceInstance != null )
			{
				referenceInstance.physicalUpdate = false;
			}

			// remove all unnecessary components, this will prevent rendering and any unexpected behaviour from custom scripts
			Component[] components = referenceObject.GetComponentsInChildren<Component>();
			for( int i = 0; i < components.Length; ++i )
			{
				Component c = components[i];
				if( c.GetType() != typeof( Transform )
					&& components[i].GetType() != typeof( CustomSkelTransformsInstance ) )
				{
					GameObject.DestroyImmediate( c );
				}
			}

			return true;
		}

		public void Release()
		{
			if( referenceObject != null )
			{
				GameObject.DestroyImmediate( referenceObject );
				referenceObject = null;
				referenceTransforms = null;
			}
		}

		public bool Initiated()
		{
			return referenceObject != null && referenceTransforms != null;
		}

		public GameObject GetReferenceObject()
		{
			return referenceObject;
		}

		public Transform[] GetReferenceTransforms()
		{
			return referenceTransforms;
		}

		bool CheckRigidbodies( Transform[] transforms )
		{
			if( transforms == null )
			{
				return false;
			}

			bool ret = true;
			for( int i = 0; i < transforms.Length; ++i )
			{
				Transform t = transforms[i];
				if( t != null )
				{
					if( t.GetComponent<Rigidbody>() == null )
					{
						ret = false;
						break;
					}
				}
			}

			return ret;
		}
	}
}
